﻿using CMS.Constants;
using CMS.Controls.Events;
using CMS.Infos;
using CMS.REST;
using CMS.Util;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Forms;

namespace CMS.Dialogs
{
    public partial class CourseEditDialog : Form
    {
        #region 内部字段
        /// <summary>
        /// 主数据源(课表信息)
        /// </summary>
        private BindingSource _BindingSource = new BindingSource() { DataSource = new CourseRoom() };

        /// <summary>
        /// 副数据源(学期信息)
        /// </summary>
        private BindingSource _BindingSource2 = new BindingSource() { DataSource = new Term() };

        /// <summary>
        /// 副数据源(课室信息)
        /// </summary>
        private BindingSource _BindingSource3 = new BindingSource() { DataSource = new Room() };

        /// <summary>
        /// 自动填充数据源(上课班级)
        /// </summary>
        private BindingSource _BindingSource4 = new BindingSource() { DataSource = new List<string>() };

        /// <summary>
        /// 自动填充数据源(任课教师)
        /// </summary>
        private BindingSource _BindingSource5 = new BindingSource() { DataSource = new List<string>() };

        /// <summary>
        /// 当前正在编辑的课程的原始对象(注意是此对象的副本被修改,提交时,将会修改此对象)
        /// </summary>
        private CourseRoom _Selected = null;

        #endregion

        #region 事件
        /// <summary>
        /// 当编辑框确认向服务器提交了数据之后,发射此事件进行数据同步(将数据映射到窗体上去)
        /// </summary>
        public event EventHandler<SyncCourseEventArgs> OnSync;


        #endregion

        #region 公共属性
        /// <summary>
        /// 是否是新创建课程
        /// </summary>
        public bool IsNew { get; set; } = false;

        /// <summary>
        /// 当前的编辑的课程信息
        /// </summary>
        public CourseRoom CurCourse
        {
            get => (CourseRoom)_BindingSource.DataSource;
            set
            {
                _BindingSource.DataSource = value?.Clone() ?? throw new ArgumentNullException(nameof(CurRoom));
                _BindingSource.ResetBindings(false);
                _Selected = value;
            }
        }

        /// <summary>
        /// 当前的学期
        /// </summary>
        public Term CurTerm { get => (Term)_BindingSource2.DataSource; set => _BindingSource2.DataSource = value ?? throw new ArgumentNullException(nameof(CurTerm)); }

        /// <summary>
        /// 当前的课室
        /// </summary>
        public Room CurRoom { get => (Room)_BindingSource3.DataSource; set => _BindingSource3.DataSource = value ?? throw new ArgumentNullException(nameof(CurRoom)); }


        #endregion


        public CourseEditDialog()
        {
            InitializeComponent();
            InitializeComponent2();
        }

        /// <summary>
        /// 刷新自动填充源
        /// </summary>
        private void _RefreshAutoCompleteList()
        {
            {
                List<string> list = _BindingSource4.DataSource as List<string>;
                RESTResponse response = RESTClient.IndexManaged("apis/v1/class_names");

                string current = _BindingSource4.Position != -1 ? (string)_BindingSource4.Current : null;
                list.Clear();
                if (response.IsSuccess)
                {
                    list.AddRange(response.Data.ToObject<string[]>());
                }

                if (!list.Contains(current) && current != null)
                {
                    list.Add(current);
                }
                _BindingSource4.ResetBindings(false);
            }

            {
                List<string> list = _BindingSource5.DataSource as List<string>;

                RESTResponse response = RESTClient.IndexManaged("apis/v1/teacher_names");
                string current = _BindingSource5.Position != -1 ? (string)_BindingSource5.Current : null;
                list.Clear();
                if (response.IsSuccess)
                {
                    list.AddRange(response.Data.ToObject<string[]>());
                }

                if (!list.Contains(current) && current != null)
                {
                    list.Add(current);
                }
                _BindingSource5.ResetBindings(false);
            }
        }

        /// <summary>
        /// 初始化FormPanel
        /// </summary>
        private void InitializeComponent2()
        {
            var layout = FP_Main.LayoutD;
            layout.RowHeight = 30;
            FP_Main.LayoutD= layout;
            _RefreshAutoCompleteList();
            FP_Main.SuspendLayout();
            bool textBoxValidator(Control control) => !string.IsNullOrWhiteSpace(control.Text);
            bool comboBoxValidator(Control control) => ((ComboBox)control).SelectedIndex != -1;
            bool timeValidator(Control control) => !string.IsNullOrWhiteSpace(control.Text) && Utils.ValidateTime(control.Text);

            TextBox termTextBox = new TextBox() { ReadOnly = true };
            termTextBox.DataBindings.Add("Text", _BindingSource2, "Name");
            FP_Main.AddField("学期", termTextBox, null);

            TextBox roomTextBox = new TextBox() { ReadOnly = true };
            roomTextBox.DataBindings.Add("Text", _BindingSource3, "Name");
            FP_Main.AddField("课室", roomTextBox, null);

            ComboBox weekCombobox = new ComboBox()
            {
                DataSource = Constant.WeekMap,
                DisplayMember = "Key",
                ValueMember = "Value",
                DropDownStyle = ComboBoxStyle.DropDownList
            };
            weekCombobox.DataBindings.Add("SelectedValue", _BindingSource, "Week");
            FP_Main.AddField("星期", weekCombobox, comboBoxValidator);

            TextBox nameTextBox = new TextBox();
            nameTextBox.DataBindings.Add("Text", _BindingSource, "Name");
            FP_Main.AddField("课程名", nameTextBox, textBoxValidator);

            ComboBox classNameComboBox = new ComboBox
            {
                AutoCompleteMode = AutoCompleteMode.SuggestAppend,
                AutoCompleteSource = AutoCompleteSource.ListItems,
                DataSource = _BindingSource4,
            };
            classNameComboBox.DataBindings.Add("Text", _BindingSource, "ClassName");
            FP_Main.AddField("上课班级", classNameComboBox, textBoxValidator);

            ComboBox teacherComboBox = new ComboBox
            {
                AutoCompleteMode = AutoCompleteMode.SuggestAppend,
                AutoCompleteSource = AutoCompleteSource.ListItems,
                DataSource = _BindingSource5
            };
            teacherComboBox.DataBindings.Add("Text", _BindingSource, "Teacher");
            FP_Main.AddField("任课教师", teacherComboBox, textBoxValidator);

            TextBox classWeekTextBox = new TextBox();
            classWeekTextBox.DataBindings.Add("Text", _BindingSource, "ClassWeek");
            FP_Main.AddField("上课周次", classWeekTextBox, timeValidator);

            TextBox classTimeTextBox = new TextBox();
            classTimeTextBox.DataBindings.Add("Text", _BindingSource, "ClassTime");
            FP_Main.AddField("上课节次", classTimeTextBox, timeValidator);

            NumericUpDown numericUpDown = new NumericUpDown() { Maximum = 1000 };
            numericUpDown.DataBindings.Add("Value", _BindingSource, "StudentCount");
            FP_Main.AddField("学生人数", numericUpDown, null);
            FP_Main.ResumeLayout();
        }

        /// <summary>
        /// 恢复数据按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Bn_Recover_Click(object sender, EventArgs e)
        {
            _BindingSource.DataSource = _Selected.Clone();
            _RefreshAutoCompleteList();
        }

        private void Bn_Save_Click(object sender, EventArgs e)
        {
            if (FP_Main.Validate())
            {
                CourseRoom newCourse = (CourseRoom)_BindingSource.DataSource;

                if (IsNew)
                {
                    RESTResponse response = RESTClient.SaveManaged("apis/v1/courses_room", JObject.FromObject(newCourse));
                    if (response.IsSuccess)
                    {
                        newCourse.ID = response.Data[0].ToObject<int>();
                        _Selected.Assign(newCourse);
                        OnSync?.Invoke(this, new SyncCourseEventArgs(_Selected, IsNew));
                        DialogResult = DialogResult.OK;
                        return;
                    }
                    else
                    {
                        string msg = response.ErrMsg;
                        if (response.Status == RESTClient.STATUS_INVALD_PARAM)
                        {
                            if (msg.IndexOf("冲突") != -1)
                            {
                                int[] ids = response.Data.ToObject<int[]>();
                                response = RESTClient.Index("apis/v1/courses_room", new RESTWhere("id", "in", ids));
                                if (response.IsSuccess)
                                {
                                    CourseRoom[] courses = response.Data.ToObject<CourseRoom[]>();
                                    MessageBox.Show(this, $"保存课程[{newCourse.Name}]失败,原因:与已存在的课程存在冲突\r\n{string.Join<CourseRoom>("\r\n", courses)}");
                                    return;
                                }
                            }
                        }
                        MessageBox.Show(this, $"保存课程[{newCourse.Name}]失败,原因:{msg}");
                    }
                }
                else
                {
                    RESTResponse response = RESTClient.UpdateManaged("apis/v1/courses_room", newCourse.ID.ToString(), JObject.FromObject(newCourse));
                    if (response.IsSuccess)
                    {
                        Debug.Assert(newCourse.ID == _Selected.ID, "修改前后ID不可以发生改变");
                        _Selected.Assign(newCourse);
                        OnSync?.Invoke(this, new SyncCourseEventArgs(_Selected, IsNew));
                        DialogResult = DialogResult.OK;
                        return;
                    }
                    else
                    {
                        string msg = response.ErrMsg;
                        if (response.Status == RESTClient.STATUS_INVALD_PARAM)
                        {
                            if (msg.IndexOf("冲突") != -1)
                            {
                                int[] ids = response.Data.ToObject<int[]>();
                                response = RESTClient.Index("apis/v1/courses_room", new RESTWhere("id", "in", ids));
                                if (response.IsSuccess)
                                {
                                    CourseRoom[] courses = response.Data.ToObject<CourseRoom[]>();
                                    MessageBox.Show(this, $"保存课程[{_Selected.Name}]失败,原因:与已存在的课程存在冲突\r\n{string.Join<CourseRoom>("\r\n", courses)}");
                                    return;
                                }
                            }
                        }
                        MessageBox.Show(this, $"保存课程[{_Selected.Name}]失败,原因:{msg}");
                    }
                }
            }
            else
            {
                MessageBox.Show(this, "信息填写有误,请检查后重新提交", "信息错误");
            }
        }

        private void Bn_Cancel_Click(object sender, System.EventArgs e)
        {
            Hide();
        }

        private void CourseEditDialog_FormClosing(object sender, FormClosingEventArgs e)
        {
            Hide();
        }


        private void CourseEditDialog_Shown(object sender, EventArgs e)
        {
            FP_Main.Validate();
        }
    }
}
